
from typing import Generator

from django.conf import settings
from cozepy import Coze, TokenAuth, Message, ChatEventType, MessageObjectString

from cozepy import File
import requests
from io import BytesIO
import logging

# from cozepy.chat import MessageContent, ImageUrl  # 导入必要的类


class CozeResumeService:
    """简历助手Coze智能体服务封装（保留图片支持，移除文件上传）"""
    def __init__(self):
        self.coze = Coze(
            auth=TokenAuth(token=settings.COZE_API_TOKEN1),
            base_url=settings.COZE_CN_BASE_URL,
        )
        self.bot_id = settings.COZE_RESUME_BOT_ID
        self.logger = logging.getLogger(__name__)

    def upload_image(self, image_url: str) -> File:
        """保留图片上传逻辑（不变）"""
        try:
            response = requests.get(image_url, timeout=10)
            response.raise_for_status()
            image_stream = BytesIO(response.content)
            return self.coze.files.upload(file=image_stream)
        except Exception as e:
            self.logger.error(f"图片上传失败: {str(e)}")
            raise ValueError(f"图片上传失败: {str(e)}")

    def stream_chat(self, final_prompt: str, user_id: str = "123456789", image_url: str = None) -> Generator[str, None, None]:
        """移除file_id参数，仅保留文本和图片处理"""
        if not final_prompt.strip():
            raise ValueError("Prompt不能为空")

        # 构建消息对象（文本+图片）
        message_objects = [MessageObjectString.build_text(final_prompt)]
        image_file_id = None
        if image_url:
            try:
                file = self.upload_image(image_url)
                image_file_id = file.id
                message_objects.append(MessageObjectString.build_image(file_id=image_file_id))
            except Exception as e:
                yield f"[ERROR]图片处理失败: {str(e)}"
                return

        # 构造用户消息
        additional_messages = [
            Message.build_user_question_objects(message_objects)
        ]

        self.logger.info(f"Coze请求参数：prompt={final_prompt[:50]}..., 图片file_id={image_file_id or '无'}")

        try:
            for event in self.coze.chat.stream(
                    bot_id=self.bot_id,
                    user_id=user_id,
                    additional_messages=additional_messages,
                    timeout=30,
            ):
                if event.event == ChatEventType.ERROR:
                    error_msg = event.data.get("msg", "Coze服务错误")
                    self.logger.error(f"Coze错误：{error_msg}")
                    yield f"[ERROR]{error_msg}"
                    return
                elif event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:
                    if event.message.content.strip():
                        yield event.message.content
                elif event.event == ChatEventType.CONVERSATION_CHAT_COMPLETED:
                    yield "[DONE]"
        except Exception as e:
            self.logger.error(f"Coze调用异常：{str(e)}", exc_info=True)
            yield f"[ERROR]调用Coze失败：{str(e)}"

        message_objects = [MessageObjectString.build_text(final_prompt)]




        # 如果有图片URL，先上传获取file_id
        if image_url:
            try:
                file = self.upload_image(image_url)
                message_objects.append(MessageObjectString.build_image(file_id=file.id))
            except Exception as e:
                yield f"[ERROR]图片处理失败: {str(e)}"
                return

        # 构造符合官方规范的消息
        additional_messages = [
            Message.build_user_question_objects(message_objects)
        ]

        # 构建符合Coze要求的消息内容
        # 1. 文本内容作为主content
        content = final_prompt
        # 2. 如果有图片，通过extra参数传递（根据Coze SDK规范）
        extra = None
        if image_url:
            extra = {
                "attachments": [
                    {
                        "type": "image_url",
                        "image_url": {"url": image_url}
                    }
                ]
            }

        # 构造Message对象（严格指定role、content和content_type）
        additional_messages = [
            Message(
                role="user",
                content=content,  # 主内容必须是字符串
                content_type="text",  # 明确指定内容类型
                extra=extra  # 附加信息（图片等）
            )
        ]

        # 日志打印
        import logging
        logger = logging.getLogger(__name__)
        logger.info(f"Coze 接收到的 prompt：{final_prompt}")
        logger.info(f"Coze 接收到的图片URL：{image_url}")

        try:
            for event in self.coze.chat.stream(
                    bot_id=self.bot_id,
                    user_id=user_id,
                    additional_messages=additional_messages,
                    timeout=30,
            ):
                if event.event == ChatEventType.ERROR:
                    error_msg = event.data.get("msg", "Coze 内部错误")
                    logger.error(f"Coze 错误：{error_msg}")
                    yield f"[ERROR]{error_msg}"
                    return
                elif event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:
                    if event.message.content.strip():
                        yield event.message.content
                elif event.event == ChatEventType.CONVERSATION_CHAT_COMPLETED:
                    yield "[DONE]"
        except Exception as e:
            logger.error(f"Coze 调用异常：{str(e)}", exc_info=True)
            yield f"[ERROR]调用 Coze 失败：{str(e)}"

        # # 调用Coze流式接口（传递最终Prompt）
        # for event in self.coze.chat.stream(
        #     bot_id=self.bot_id,
        #     user_id=user_id,
        #     # 构造用户消息：包含简历的最终需求
        #     additional_messages=[Message.build_user_question_text(final_prompt)],
        #     # 可选：设置会话超时（避免重复会话）
        #     timeout=30,
        # ):
        #     # 1. 返回AI的增量回复（前端实时显示）
        #     if event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:
        #         # 过滤空内容，避免前端接收无效数据
        #         if event.message.content.strip():
        #             yield event.message.content
        #     # 2. 回复结束：返回[DONE]标记
        #     elif event.event == ChatEventType.CONVERSATION_CHAT_COMPLETED:
        #         yield "[DONE]"
        #     # 3. Coze返回错误：捕获并返回[ERROR]
        #     elif event.event == ChatEventType.ERROR:
        #         error_msg = event.data.get("msg", "Coze服务内部错误")
        #         yield f"[ERROR]{error_msg}"
